ctypes
是一个方便 Python
调用本地已经编译好的外部库的模块。
from ctypes import util, CDLL
使用 util
来找到标准 C
库:
libc_name = util.find_library('c')
# on WINDOWS
print libc_name
使用 CDLL
来加载 C
库:
libc = CDLL(libc_name)
libc 包含 C
标准库中的函数:
libc.printf
调用这个函数:
libc.printf("%s, %d\n", "hello", 5)
这里显示的 9
是 printf
的返回值表示显示的字符串的长度(包括结尾的 '\0'
),但是并没有显示结果,原因是 printf
函数默认是写在标准输出流上的,与 IPython
使用的输出流不一样,所以没有显示结果。
找到数学库:
libm_name = util.find_library('m')
print libm_name
调用 atan2
函数:
libm = CDLL(libm_name)
libm.atan2(1.0, 2.0)
调用这个函数出错,原因是我们需要进行一些额外工作,告诉 Python
函数的参数和返回值是什么样的:
from ctypes import c_double
libm.atan2.argtypes = [c_double, c_double]
libm.atan2.restype = c_double
libm.atan2(1.0, 2.0)
与 Python
数学库中的结果一致:
from math import atan2
atan2(1.0, 2.0)
假设我们有这样的一个函数:
float _sum(float *vec, int len) {
float sum = 0.0;
int i;
for (i = 0; i < len; i++) {
sum += vec[i];
}
return sum
}
并且已经编译成动态链接库,那么我们可以这样调用:
from ctypes import c_float, CDLL, c_int
from numpy import array, float32
from numpy.ctypeslib import ndpointer
x = array([1,2,3,4], dtype=float32)
lib = CDLL(<path>)
ptr = ndpointer(float32, ndim=1, flags='C')
lib._sum.argtypes = [ptr, c_int]
lib._sum.restype = c_float
result = lib._sum(x, len(x))